using System;
using System.Collections.Generic;

using System.Text;

using Mud.Common;
using Mud.Common.Messages;
using Mud.Common.Physical;

namespace Mud.Client.EventHandlers
{



    [MessageHandler(MessageTypeIds.EventCreatureAppeared)]
    public sealed class EventCreatureAppeared : IEventHandler
    {
        #region IEventHandler Members

        void IEventHandler.Handle(Mud.Common.Messages.IMessage e, Client client)
        {
            MessageEventCreatureAppeared m = MessageHelper.AssertIsMessage<MessageEventCreatureAppeared>(e);
            if (client.PlayerArea.Creatures.ContainsKey(m.Creature.ObjectInfo.ObjectId))
            {
                Logger.Log(LogType.Error, "EventCreatureAppeared.Handle", "New creature {0} ({1}) appeared which has the same object Id as already existing creature {2} ({3}).", m.Creature.ObjectInfo.ObjectId, m.Creature.ObjectInfo.ObjectName, client.PlayerArea.Creatures[m.Creature.ObjectInfo.ObjectId].ObjectId, client.PlayerArea.Creatures[m.Creature.ObjectInfo.ObjectId].Name);
                client.PlayerArea.RemoveCreature(m.Creature.ObjectInfo.ObjectId);
            }
            client.PlayerArea.AddCreature(MessageToObjectMapper.MapToObject(m.Creature));
            Logger.Log(LogType.Debug, "EventCreatureAppeared.Handle", "New creature {0} ({1}) appeared.", m.Creature.ObjectInfo.ObjectId, m.Creature.ObjectInfo.ObjectName);
        }

        #endregion
    }


    [MessageHandler(MessageTypeIds.EventCreatureDisappeared)]
    public sealed class EventCreatureDisappeared : IEventHandler
    {
        #region IEventHandler Members

        void IEventHandler.Handle(Mud.Common.Messages.IMessage e, Client client)
        {
            MessageEventCreatureDisappeared m = 
                MessageHelper.AssertIsMessage<MessageEventCreatureDisappeared>(e);

            if (!client.PlayerArea.Creatures.ContainsKey(m.CreatureId))
            {
                Logger.Log(LogType.Error, "EventCreatureDisappeared.Handle", "Creature {0} has disapeared, but there is no such creature.", m.CreatureId);
                return;
            }
            Logger.Log(LogType.Debug, "EventCreatureDisappeared.Handle", "Creature {0} ({1}) dissapeared.", client.PlayerArea.Creatures[m.CreatureId].ObjectId, client.PlayerArea.Creatures[m.CreatureId].Name);
            client.PlayerArea.RemoveCreature(m.CreatureId);
        }

        #endregion
    }

    [MessageHandler(MessageTypeIds.EventCreatureStartedMoving)]
    public sealed class EventCreatureStartedMoving : IEventHandler
    {
        #region IEventHandler Members

        void IEventHandler.Handle(Mud.Common.Messages.IMessage e, Client client)
        {
            MessageEventCreatureStartedMoving m = MessageHelper.AssertIsMessage<MessageEventCreatureStartedMoving>(e);
            Creature creature = client.PlayerArea.Creatures[m.CreatureId];
            Logger.Log(LogType.Debug, "EventCreatureStartedMoving.Handle", "Creature {0} started moving to {1}.", m.CreatureId, new Location(m.X, m.Y));
        }

        #endregion
    }

    [MessageHandler(MessageTypeIds.EventCreatureEndedMoving)]
    public sealed class EventCreatureEndedMoving : IEventHandler
    {
        #region IEventHandler Members

        void IEventHandler.Handle(Mud.Common.Messages.IMessage e, Client client)
        {
            MessageEventCreatureEndedMoving m = MessageHelper.AssertIsMessage<MessageEventCreatureEndedMoving>(e);
            Creature creature = client.PlayerArea.Creatures[m.CreatureId];
            creature.Location = new Location(m.X, m.Y);
            Logger.Log(LogType.Debug, "EventCreatureEndedMoving.Handle", "Creature {0} ended moving at {1}.", m.CreatureId, creature.Location);
        }

        #endregion
    }


    [MessageHandler(MessageTypeIds.EventCreatureEnteredArea)]
    public sealed class EventCreatureEnteredArea : IEventHandler
    {
        #region IEventHandler Members

        void IEventHandler.Handle(Mud.Common.Messages.IMessage e, Client client)
        {
            MessageEventCreatureEnteredArea m = MessageHelper.AssertIsMessage<MessageEventCreatureEnteredArea>(e);
            Logger.Log(LogType.Debug, "EventCreatureEnteredArea.Handle", "Creature {0} ({1}) entered area.", client.PlayerArea.Creatures[m.Creature.ObjectInfo.ObjectId].ObjectId, client.PlayerArea.Creatures[m.Creature.ObjectInfo.ObjectId].Name);

            if (m.Creature.ObjectInfo.ObjectId == client.PlayerCharacter.ObjectId)
            {
                if (client.PlayerArea.Creatures.ContainsKey(m.Creature.ObjectInfo.ObjectId))
                    return;
                client.PlayerArea = new Area(0, 0);
                client.PlayerArea.Name = m.AreaName;
                client.PlayerArea.AddCreature(client.PlayerCharacter);
                return;
            }

            if (client.PlayerArea.Creatures.ContainsKey(m.Creature.ObjectInfo.ObjectId))
            {
                Logger.Log(LogType.Error, "EventCreatureEnteredArea.Handle", "New creature {0} ({1}) appeared which has the same object Id as already existing creature {2} ({3}).", m.Creature.ObjectInfo.ObjectId, m.Creature.ObjectInfo.ObjectName, client.PlayerArea.Creatures[m.Creature.ObjectInfo.ObjectId].ObjectId, client.PlayerArea.Creatures[m.Creature.ObjectInfo.ObjectId].Name);
                client.PlayerArea.RemoveCreature(m.Creature.ObjectInfo.ObjectId);
            }
            Creature creature = MessageToObjectMapper.MapToObject(m.Creature);
            client.PlayerArea.AddCreature(creature);
        }

        #endregion
    }


    [MessageHandler(MessageTypeIds.EventCreatureExitedArea)]
    public sealed class EventCreatureExitedArea : IEventHandler
    {
        #region IEventHandler Members

        void IEventHandler.Handle(Mud.Common.Messages.IMessage e, Client client)
        {
            MessageEventCreatureExitedArea m = MessageHelper.AssertIsMessage<MessageEventCreatureExitedArea>(e);
            client.PlayerArea.RemoveCreature(m.CreatureId);
            Logger.Log(LogType.Debug, "EventCreatureExitedArea.Handle", "Creature {0} exited area.", m.CreatureId);
        }

        #endregion
    }


    [MessageHandler(MessageTypeIds.EventCreatureTurned)]
    public sealed class EventCreatureTurned : IEventHandler
    {
        #region IEventHandler Members

        void IEventHandler.Handle(IMessage e, Client client)
        {
            MessageEventCreatureTurned m = MessageHelper.AssertIsMessage<MessageEventCreatureTurned>(e);
            Creature creature = client.PlayerArea.Creatures[m.CreatureId];
            creature.Orientation = m.Direction;
            Logger.Log(LogType.Debug, "EventCreatureTurned.Handle", "Creature {0} turned to face {1}.", m.CreatureId, m.Direction);
        }

        #endregion
    }



    [MessageHandler(MessageTypeIds.EventClientConnected)]
    public sealed class EventClientConnected : IEventHandler
    {
        #region IEventHandler Members

        void IEventHandler.Handle(Mud.Common.Messages.IMessage e, Client client)
        {
            MessageEventClientConnected m = MessageHelper.AssertIsMessage<MessageEventClientConnected>(e);
            Logger.Log(ClientLogTypes.Status, "EventClientConnected.Handle", "User {0} has connected to the server.", m.ClientName);
        }

        #endregion
    }

    [MessageHandler(MessageTypeIds.EventClientDisconnected)]
    public sealed class EventClientDisconnected : IEventHandler
    {
        #region IEventHandler Members

        void IEventHandler.Handle(Mud.Common.Messages.IMessage e, Client client)
        {
            MessageEventClientDisconnected m = MessageHelper.AssertIsMessage<MessageEventClientDisconnected>(e);
            Logger.Log(ClientLogTypes.Status, "EventClientDisconnected.Handle", "User {0} has disconnected from the server.", m.ClientName);
            if (m.ClientName == client.UserName) // this is me!
            {
                client.Disconnect();
            }
        }

        #endregion
    }






    [MessageHandler(MessageTypeIds.EventSimpleObjectAppeared)]
    public sealed class EventSimpleObjectAppeared : IEventHandler
    {
        #region IEventHandler Members

        void IEventHandler.Handle(Mud.Common.Messages.IMessage e, Client client)
        {
            MessageEventSimpleObjectAppeared m = MessageHelper.AssertIsMessage<MessageEventSimpleObjectAppeared>(e);
            if (client.PlayerArea.SimpleObjects.ContainsKey(m.SimpleObject.ObjectInfo.ObjectId))
            {
                Logger.Log(LogType.Error, "EventSimpleObjectAppeared.Handle", "New object {0} appeared which has the same object Id as already existing object.", m.SimpleObject.ObjectInfo.ObjectId);
                client.PlayerArea.RemoveObject(m.SimpleObject.ObjectInfo.ObjectId);
            }
            client.PlayerArea.AddObject(MessageToObjectMapper.MapToObject(m.SimpleObject));
            Logger.Log(LogType.Debug, "EventSimpleObjectAppeared.Handle", "New object {0} appeared.", m.SimpleObject.ObjectInfo.ObjectName);
        }

        #endregion
    }


    [MessageHandler(MessageTypeIds.EventSimpleObjectDisappeared)]
    public sealed class EventSimpleObjectDisappeared : IEventHandler
    {
        #region IEventHandler Members

        void IEventHandler.Handle(Mud.Common.Messages.IMessage e, Client client)
        {
            MessageEventSimpleObjectDisappeared m =
                MessageHelper.AssertIsMessage<MessageEventSimpleObjectDisappeared>(e);
            if (!client.PlayerArea.SimpleObjects.ContainsKey(m.SimpleObjectId))
            {
                Logger.Log(LogType.Error, "EventSimpleObjectDisappeared.Handle", "Object {0} has disapeared, but there is no such object.", m.SimpleObjectId);
                return;
            }
            client.PlayerArea.RemoveObject(m.SimpleObjectId);
            Logger.Log(LogType.Debug, "EventSimpleObjectDisappeared.Handle", "Object {0} dissapeared.", m.SimpleObjectId);
        }

        #endregion
    }




    [MessageHandler(MessageTypeIds.EventAreaChanged)]
    public sealed class EventAreaChanged : IEventHandler
    {
        #region IEventHandler Members

        void IEventHandler.Handle(Mud.Common.Messages.IMessage e, Client client)
        {
            MessageEventAreaChanged m = MessageHelper.AssertIsMessage<MessageEventAreaChanged>(e);
            client.PlayerArea = new Area(m.Area.AreaXDimension, m.Area.AreaYDimension);
            client.PlayerArea.Name = m.Area.AreaName;
            client.PlayerArea.AddCreature(client.PlayerCharacter);
            Logger.Log(ClientLogTypes.Status, "EventAreaChanged.Handle", "You've entered area {0}.", client.PlayerArea.Name);
        }

        #endregion
    }


    [MessageHandler(MessageTypeIds.EventAreaLandChanged)]
    public sealed class EventAreaLandChanged : IEventHandler
    {
        #region IEventHandler Members

        void IEventHandler.Handle(Mud.Common.Messages.IMessage e, Client client)
        {
            MessageEventAreaLandChanged m = MessageHelper.AssertIsMessage<MessageEventAreaLandChanged>(e);
            for (int x = 0; x < m.Land.Width; x++)
                for (int y = 0; y < m.Land.Height; y++)
                {
                    AreaLandSquare square = new AreaLandSquare(m.Land.Terrain[x, y], x, y);
                    client.PlayerArea.SetLand(square);
                }

            Rectangle rect = new Rectangle(m.Land.XOffset, m.Land.YOffset, m.Land.Width, m.Land.Height);
            Logger.Log(LogType.Debug, "EventAreaLandChanged.Handle", "Got new area land information for area part {0}.", rect);
        }

        #endregion
    }
}
